(function(global,factory){
    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
    typeof define === 'function' && define.amd ? define(factory) :
    (global = global || self, global.topicTable = factory());
}(this,function(){
    let TOPICCASE = 'TOPIC_TYPE_CASE'
    , MINSCORE = 1
    , MINTOPICCOUNT = 1
    , style = document.createElement('style')
    , styleText = [
        '.topic-table table{width: 100%;text-align:center;border-collapse: collapse;line-height: 24px;font: 14px Helvetica Neue,Helvetica,PingFang SC,Tahoma,Arial,sans-serif;}',
        '.topic-table-cell{padding:8px;}',
        '.topic-table-first-cell{text-align: left;}',
        '.topic-table table td,.topic-table table th{border: 1px solid #E3E3E3;}',
        '.topic-table-input{width: 40px;height: 30px;display: inline-block;border: 1px solid #E3E3E3;text-align:center}',
        '.topic-table-input:focus{outline: none;}',
        '.topic-table-separator{display: inline-block;margin: 0 5px;}',
        '.topic-table .show-topic-table{display: table;}',
        '.topic-table .layui-inline{display: inline-block;vertical-align: middle;}',
        '.topic-table .layui-btn{display: inline-block;height: 38px;line-height: 38px;padding: 0 18px;background-color: #009688;color: #fff;white-space: nowrap;text-align: center;font-size: 14px;border: none;border-radius: 2px;cursor: pointer;outline: 0;-webkit-appearance: none;transition: all .3s;-webkit-transition: all .3s;box-sizing: border-box;}',
        '.topic-table .layui-btn-xs{height: 22px;line-height: 22px;padding: 0 5px;font-size: 12px;}',
        '.topic-table .layui-btn-danger{background-color: #FF5722;}'
    ].join("")
    style.innerHTML = styleText;
    document.getElementsByTagName('body')[0].appendChild(style);
    let topicType = {
        'TOPIC_TYPE_RADIO':'单选题'
        ,'TOPIC_TYPE_MULTIPLE':'多选题'
        ,'TOPIC_TYPE_ANSWER':'简答题'
        ,'TOPIC_TYPE_UNDEFINED':'不定项选择题'
        ,'TOPIC_TYPE_TRUE_FALSE':'判断题'
        ,'TOPIC_TYPE_FILLING':'填空题'
        ,'TOPIC_TYPE_CASE':'材料题'
    }
    , difficulty = {
        'DIFFICULT_TYPE_EASY':'简单'
        ,'DIFFICULT_TYPE_MIDDLE':'一般'
        ,'DIFFICULT_TYPE_DIFFICULT':'困难'
    }
    , diffs = ['DIFFICULT_TYPE_EASY','DIFFICULT_TYPE_MIDDLE','DIFFICULT_TYPE_DIFFICULT']
    , topicTypeSort = ['TOPIC_TYPE_RADIO','TOPIC_TYPE_MULTIPLE','TOPIC_TYPE_UNDEFINED','TOPIC_TYPE_TRUE_FALSE','TOPIC_TYPE_FILLING','TOPIC_TYPE_ANSWER','TOPIC_TYPE_CASE']
    , isInit = true
    , dftOpt = {
        el:'#topic-table'
        ,data:null
        ,type:'random'
        ,inputData:null
        ,isDepOldIns:true//为false时，必须提供inputData数据
        ,createBefore:function(){}
    }
    , TopicTable = function(options){
        this.setting = $.extend(true,{},dftOpt,options)
        this.el = TopicTable.Utils.getEl(this.setting.el)
        this.data = null;
        this.table = null;
        this.inputData = null;
        this.init();
    };

    TopicTable.Utils = {
        getEl:function(selector){
            if(selector && (selector.nodeType != Node.ELEMENT_NODE || selector.nodeType == Node.DOCUMENT_NODE)){
                selector = /^#[^#\s\b]+$/.test(selector) ? document.querySelector(selector) : document.querySelectorAll(selector)
            }
            return selector;
        }
        ,search:function(str,reg){
            let result = [] ,match;
            while(match = reg.exec(str)){
                match.forEach(function(item,i){
                    i > 0 && item && result.push(item);
                })
            }
            return result;
        }
        ,parSubTree:function(nodes,pNodeId,nodeId){
            pNodeId = pNodeId || 'parentId'
            nodeId = nodeId || 'id'
            let nodePoint = {},newNodes = [];
            // 删除所有topicList属性,以防止多次调用
            nodes.forEach(node=>{
                delete node.topicList;
            });
            nodes.forEach(node=>{
                !node.topicId && (node.topicId = node.id) 
                nodePoint[node[nodeId]] = node;
            });
            nodes.forEach(node=>{
                if(node[pNodeId] in nodePoint){
                    (nodePoint[node[pNodeId]].topicList || (nodePoint[node[pNodeId]].topicList = [])).push(node);
                }else{//不在则是顶级节点
                    newNodes.push(node);
                }
            });
            return newNodes;
        }
        //获取数据结构
        ,getDataStruct:function(data){
            let utils = TopicTable.Utils
            //定义数据结构
            ,dataStruct = function(data,saveObj){
                data.forEach(function(item){
                    let topicType = item.topicType
                    , diff = item.difficulty
                    , topicTypes;
                    if(topicType == TOPICCASE){
                        topicTypes = saveObj[topicType] || (saveObj[topicType] = []);
                        topicTypes.push(item);
                        let childs = item.childs || (item.childs = {});
                        utils.exist(item.topicList) && dataStruct(item.topicList,childs)
                    }else{
                        topicTypes = saveObj[topicType] || (saveObj[topicType] = {});
                        (topicTypes[diff]||(topicTypes[diff] = [])).push(item)
                    }
                });
                return saveObj;
            };
            data.forEach(function(item){
                item.childs && (item.childs = null)
            })
            utils.setSortFlag(data);
            utils.sort(data);
            return dataStruct(data,{});
        }
        //设置排序标识
        ,setSortFlag:function(data){
            let utils =TopicTable.Utils;
            data.forEach(function(item){
                //题目类型排序标识
                item.typeSort = topicTypeSort.indexOf(item.topicType) + 1;
                //题目难易程度排序
                item.diffSort = diffs.indexOf(item['difficulty']) + 1;
                if(item.topicType == TOPICCASE && Array.isArray(item.topicList) && item.topicList.length > 0){
                    utils.setSortFlag(item.topicList);
                }
            })
        }
        //定义排序方法
        , sort:function(data){
            let utils = TopicTable.Utils;
            if(!Array.isArray(data)){return }
            if(data.length == 1){
                utils.sort(data[0].topicList);
            }else{
                return data.sort(function(a,b){
                    let flag = 0;
                    a.topicType == TOPICCASE && Array.isArray(a.topicList) && a.topicList.length > 0 && utils.sort(a.topicList)
                    b.topicType == TOPICCASE && Array.isArray(b.topicList) && b.topicList.length > 0 && utils.sort(b.topicList)
                    if(a.typeSort == b.typeSort){
                        flag = a.diffSort - b.diffSort
                    }else{
                        flag = a.typeSort - b.typeSort
                    }
                    return flag;
                })
            }
        }
        //根据列索引，合并指定行
        ,mergeRowByCol:function(table,col,startRow,endRow){
            !endRow && (endRow = table.rows.length-1);
            for(let i = startRow; i < endRow; i++) {
                let row = table.rows[i+1];
                row.deleteCell(col); 
                table.rows[startRow].cells[col].rowSpan = table.rows[startRow].cells[col].rowSpan+1;
            }
        }
        //是否含有材料题
        ,isHasCase:function(data){
            return !!data[TOPICCASE];
        }
        ,emptyObj:function(obj){
            let value = JSON.stringify(obj)
            return value == '{}' || value == '[]';
        }
        ,notExist:function(data){
            let flag = !!!data;
            //如果是数值并且小于零也认为不存在
            isFinite(data) && data < 0 && (flag = true)
            //空对象也认为不存在
            TopicTable.Utils.emptyObj(data) && (flag = true)
            return flag;
        }
        ,exist:function(data){
            let flag = true;
            //存在的是有意义的
            flag = !!data;
            //小于等于0的数，认为是不存在的
            isFinite(data) && data < 0 && (flag = false)
            TopicTable.Utils.emptyObj(data) && (flag = false)
            return flag;
        }
        //对象扁平化
        ,flatObj:function(data){
            let target = {}
            , setItem = function(data,name){
                Object.keys(data).forEach(function(key,i){
                    //将key值存储到target对象中
                    let value = data[key]
                    , reg1 = /^TOPIC_TYPE_CASE\[\d\]/
                    , reg2 = /^TOPIC_TYPE_CASE\[\d\]\[childs\]/;
                    if((typeof value == 'object' && value != null && !Array.isArray(value)) || key == TOPICCASE){
                        key = !name && key || name+'['+key+']';
                        setItem(value,key);
                    }else{
                        key = !name && key || name+'['+key+']';
                        if(reg1.test(key)){
                            if(reg2.test(key)){
                                target[key] = value
                            }
                        }else{
                            target[key] = value
                        }
                    }
                })
            };
            setItem(data);
            return target;
        }
        //对象反扁平化
        ,unflatten:function(obj){
            let utils = TopicTable.Utils;
            var result = {}, temp, substrings, i;
            for(let property in obj){
                //substrings = property.split('.');
                substrings = utils.search(property,/([^\[\]]+)(?:\[([^\[\]]+)\])*?/g)
                temp = result;
                for (i = 0; i < substrings.length - 1; i++) {
                    if (!(substrings[i] in temp)) {
                        if (isFinite(substrings[i + 1])) { 
                            temp[substrings[i]] = [];      
                        } else {
                            temp[substrings[i]] = {};      
                        }
                    }
                    temp = temp[substrings[i]];
                }
                temp[substrings[substrings.length - 1]] = obj[property];
            }
            return result;
        }
        //获取需要合并的数据
        ,getMergeData:function(data,startRow){
            startRow = startRow||0;
            //保存不同题目类型的开始行与结束行
            let mergeData = {};
            for(let type in data){
                //材料题
                if(type == TOPICCASE){
                    //材料题有多个
                    mergeData[type] = [];
                    let cases = data[type]
                    for(let i in cases){
                        let topicCase = cases[i]
                        , prevStartRow = startRow
                        , obj = {
                            startRow:startRow
                            ,endRow:startRow +  TopicTable.Utils.getTopicTypeCount(topicCase.childs,true)-1
                        };
                        startRow = obj.endRow+1
                        obj.childs = TopicTable.Utils.getMergeData(topicCase.childs,prevStartRow);
                        mergeData[type].push(obj);
                    }
                }else{
                    mergeData[type] = {
                        startRow:startRow
                        ,endRow:startRow + Object.keys(data[type]).length-1
                    }
                }
                startRow = mergeData[type].endRow+1
            }
            return mergeData;
        }
        //合并单元格
        ,mergeCell:function(table,mergeData,col){
            let utils = TopicTable.Utils
            col = col || 0;
            for(let type in mergeData){
                let item = mergeData[type]
                //非材料题
                if(type != TOPICCASE){
                    utils.mergeRowByCol(table,col,item.startRow,item.endRow)
                }else{
                    for(let i in item){
                        let cases = item[i];
                        let lastCol = table.rows[table.rows.length-1].cells.length-1;
                        //合并最后一列删除按钮
                        utils.mergeRowByCol(table,lastCol,cases.startRow,cases.endRow);
                        //合并材料题的子题(子题是非材料题)
                        utils.mergeCell(table,cases.childs,1);
                        //合并材料题首列列单元格
                        utils.mergeRowByCol(table,0,cases.startRow,cases.endRow);
                    }
                }
            }
        }
        //获取总的题目数
        ,getTopicCount:function(obj){
            let count = 0 , utils = TopicTable.Utils;
            for(let type in obj){
                let item = obj[type];
                //不是材料题并且是保存题目数量的数组
                if(Array.isArray(item) && type != TOPICCASE){
                    count += item.length;
                }else{
                    //如果是材料题，则获取子题数
                    if(Array.isArray(item)){
                        let cases = item;
                        for(let i in cases){
                            let topicCase = cases[i];
                            count += utils.getTopicCount(topicCase.childs);
                        }
                    }else{
                        //非材料题，则直接获取题目数量
                        count += utils.getTopicCount(item);
                    }
                }
            }
            return count;
        }
        //获取题目类型数
        //isTopicTypeObj不传值，表示obj是题目困难度对象 ： {simple:[],middle:[],diffcult:[]}
        ,getTopicTypeCount:function(obj,isTopicTypeObj){
            let count = 0;
            //如果是题目对象
            if(isTopicTypeObj){
                for(let type in obj){
                    let item = obj[type];
                    if(type == TOPICCASE){
                        let cases = obj[type];
                        for(let i in cases){
                            let topicCase = cases[i];
                            count += TopicTable.Utils.getTopicTypeCount(topicCase.childs,true);
                        }
                    }else{
                        count += Object.keys(item).length;
                    }
                }
            }else{
                //困难度对象
                count += Object.keys(obj).length;
            }
            return count;
        }
        //最小题目数
        ,minTopicCount:function(obj){
            let count = 0 , utils = TopicTable.Utils;
            for(let type in obj){
                let item = obj[type];
                //材料题直接获取题目数
                if(type == TOPICCASE){
                    let cases = obj[type];
                    for(let i in cases){
                        let topicCase = cases[i];
                        count += utils.getTopicCount(topicCase.childs);
                    }
                }else{
                    //非材料题,获取题目类型数
                    count += utils.getTopicTypeCount(item);
                }
            }
            return count;
        }
        //获取input的数据结构
        ,getInputDataStruct:function(inputData){
            let utils = TopicTable.Utils
            , copyInputData = $.extend(true,{},{inputData:inputData}).inputData
            , inputDataStruct = utils.getDataStruct(copyInputData)
            , data = utils.flatObj(inputDataStruct)
            ,setRandomCountAndScore = function(topics){
                topics.forEach(function(topic,i){
                    if(utils.notExist(topic.randomCount)){
                        topic.randomCount = MINTOPICCOUNT;
                    }
                    if(utils.notExist(topic.topicScore)){
                        topic.topicScore = MINSCORE
                    }
                })
            };
            for(let expr in data){
                let topics = data[expr]
                , count = MINTOPICCOUNT
                , caseId;
                setRandomCountAndScore(topics);
                //材料题
                if(expr.indexOf(TOPICCASE) > -1){  
                    count = topics.length;
                    let index = /\d/.exec(expr)[0];
                    caseId = inputDataStruct[TOPICCASE][index].topicId;
                }else{
                    count = topics[0].randomCount;
                }
                let score = topics[0].topicScore;
                data[expr] = [count,topics.length,score];
                caseId && data[expr].push(caseId);
            }
            return utils.unflatten(data);
        }
        //获取抽题数量和总分
        ,getAllRandomCountAndTotalScore:function(obj){
            let utils = TopicTable.Utils
            , save = [0,0];
            for(let type in obj){
                let item = obj[type];
                //非材料题
                if(Array.isArray(item) && type != TOPICCASE){
                    save[0] += item[0];
                    save[1] += item[0]*item[2];
                }else{
                    //如果是材料题，则获取子题数
                    if(Array.isArray(item)){
                        let cases = item;
                        for(let i in cases){
                            let topicCase = cases[i]
                            , arr = utils.getAllRandomCountAndTotalScore(topicCase.childs);
                            save[0] += arr[0]
                            save[1] += arr[1]
                        }
                    }else{
                        //非材料题，则直接获取题目数量
                        let arr = utils.getAllRandomCountAndTotalScore(item);
                        save[0] += arr[0]
                        save[1] += arr[1]
                    }
                }
            }
            return save;
        }
        //根据表达式获取对象属性值
        ,getVal:function(data,expr){
            expr.split(".").forEach(function(attr){
                data = data[attr];
            })
            return data;
        }
        //根据表达式删除数据，如果值是空数据或空对象也会将其删除
        //data是dataStruct对象
        ,delVal:function(dataStruct,expr){
            //expr在data中的值是数组
            let utils = TopicTable.Utils
            , temp = dataStruct;
            //表达式是数组，说明是材料题
            if(/\d$/.test(expr)){
                let attrs = expr.split(".");
                attrs.forEach(function(attr,i){
                    if(attrs.length -1 == i){
                        temp.splice(attr,1);
                    }else{
                        temp = temp[attr];
                    } 
                })
            }else{
                eval('delete data'+TopicTable.Utils.getAttrs(expr))
            }
            expr = expr.substring(0,expr.lastIndexOf("."));
            let value = utils.getVal(dataStruct,expr);
            if(utils.notExist(value)){
                utils.delVal(dataStruct,expr);
            }
        }
        ,delData:function(data,expr,dataStruct){
            let utils = TopicTable.Utils
            , propertys = ['topicType','difficulty']
            , where = function(topic,expr){
                return expr.split(".").reduce(function(where,attr,i){
                    if(topic[propertys[i]] != attr){
                        where =  false;
                    }
                    return where;
                },true);
            }
            //表达式是数组，说明是材料题
            if(/\d$/.test(expr)){
                let topicCase = utils.getVal(dataStruct,expr);
                for(let i = 0; i < data.length; i++){
                    let topic = data[i];
                    if(topic == topicCase){
                        data.splice(i,1);
                        break;
                    }
                }
            }else{
                for(let i = 0; i < data.length; i++){
                    let topic = data[i];
                    where(topic,expr) && (data.splice(i,1) , i--) 
                }
            }
            return utils.emptyObj(data) ? null : data;
        }
        //将TOPIC_TYPE_CASE.0.childs===>[TOPIC_TYPE_CASE][0][childs]
        ,getAttrs:function(expr){
            let args = []
            expr.split('.').forEach(function(arg){
                args.push('["'+arg+'"]')
            })
            return args.join('');
        }
    }

    TopicTable.prototype = {
        constructor:TopicTable
        ,init:function(){
            if(TopicTable.Utils.notExist(this.setting.data)){ return $(this.el).empty(); }
            let flag = this.createBefore();
            if(flag === false){return;}
            this.create();
            this.created();
        }
        ,createBefore:function(){
            let utils = TopicTable.Utils;
            this.data = utils.getDataStruct(this.setting.data);
            this.inputData = utils.getInputDataStruct(this.setting.inputData);
            let retVal = this.setting.createBefore()
            return retVal === false ? false : utils.exist(this.data);
        }
        ,create:function(){
            let utils = TopicTable.Utils
            , data = this.data
            //是否有材料题
            , isHasCase = utils.isHasCase(data)
            , topicCountAndTotalScore = utils.getAllRandomCountAndTotalScore(this.inputData)
            //获取抽题数量
            , topicSeLectCount = topicCountAndTotalScore[0]
            , totalScore = parseFloat(topicCountAndTotalScore[1]).toFixed(1);
            
            let html = '<div class="topic-table-container">'
                    html += '<div>'
                        html += '<table>'
                            html += '<thead>'
                                html += '<tr>'
                                    html += '<th class="topic-table-first-cell" colspan="'+(isHasCase ? 7 : 6)+'"><div class="topic-table-cell">试卷共<span class="topic-count">'+topicSeLectCount+'</span>道题, 总共<span class="total-score">'+totalScore+'分</span></div></th>'
                                html += '</tr>'
                                html += '<tr>'
                                    html += '<th colspan="'+(isHasCase ? 2 : 1)+'"><div class="topic-table-cell">题型</div></th>'
                                    html += '<th><div class="topic-table-cell">难易程度</div></th>'
                                    html += '<th><div class="topic-table-cell">抽题数量设置</div></th>'
                                    html += '<th><div class="topic-table-cell">单题分值</div></th>'
                                    html += '<th><div class="topic-table-cell">总分</div></th>'
                                    html += '<th><div class="topic-table-cell">操作</div></th>'
                                html += '</tr>'
                            html += '</thead>'
                            html += '<tbody>'
                            let body = function(data,html,caseName,caseExpr){
                                html = html || '';
                                caseExpr = caseExpr || '';
                                //type题目类型
                                for(let type in data){
                                    if(type == TOPICCASE){
                                        //材料题是数组
                                        let cases = data[type];
                                        for(let i in cases){
                                            let topicCase = cases[i];
                                            let caseExpr = TOPICCASE+'.'+i+'.childs.'
                                            html += body.call(this,topicCase.childs,'',topicCase.topicName,caseExpr)
                                        }
                                    }else{
                                        //指定type题型的难易度对象
                                        let difs = data[type];
                                        //let inputDifs = this.inputData[type];
                                        for(let dif in difs){
                                            let topics = difs[dif]||0
                                            , expr = caseExpr + type+'.'+dif
                                            let value = utils.getVal(this.inputData,expr);
                                            isHasCase && caseName && (minTopicCount = topics.length);
                                            html += '<tr expr="'+expr+'">'
                                                if(caseName){
                                                    html+= '<td><div class="topic-table-cell topic-table-case">材料题-'+(caseName.substring(0,6))+'...</div></td>'
                                                }
                                                html += '<td colspan="'+(isHasCase && !caseName ? 2 : 1)+'"><div class="topic-table-cell">'+topicType[type]+'</div></td>'
                                                html += '<td><div class="topic-table-cell">'+difficulty[dif]+'</div></td>'
                                                html += '<td><div class="topic-table-cell">'
                                                    //非材料题
                                                    if(!caseName){
                                                        html += '<div class="layui-inline"><input type="text" class="layui-input topic-table-input set-topic-count" value="'+value[0]+'"/></div>'
                                                    }else{
                                                        html += '<div class="layui-inline"><div>'+value[0]+'</div></div>'
                                                    }
                                                    html += '<div class="topic-table-separator">/</div>'
                                                    html += '<div class="layui-inline topic-type-count">'+topics.length+'</div>'
                                                html += '</div></td>'
                                                html += '<td><div class="topic-table-cell"><input type="text" class="layui-input topic-table-input set-topic-value" value="'+value[2]+'"/></div>'
                                                html += '<td><div class="topic-table-cell">'+(parseFloat(value[0]*value[2]).toFixed(1))+'分</div></td>'
                                                html += '<td><div class="topic-table-cell"><a class="layui-btn layui-btn-danger layui-btn-xs del-btn">删除</a></div></td>'
                                            html += '</tr>'
                                        }
                                    }
                                }
                                return html;
                            }
                            html += body.call(this,data);
                            html += '</tbody>'
                        html += '</table>'    
                    html += '</div>'
                html+='</div>';
            this.el.innerHTML = html;  
            this.table = this.el.querySelector('table');
            //this.table.classList.add('show-topic-table');
        }
        ,created:function(){
            let utils = TopicTable.Utils
            //获取合并数据
            , mergeData = utils.getMergeData(this.data,2);
            //合并单元格
            utils.mergeCell(this.table,mergeData);
            this.eventBind();
            //设置随机类型
            this.setType(this.setting.type);
        }
        ,eventBind:function(){
            let self = this
            $(".del-btn").click(function(){
                //删除数据，重新渲染表格
                let expr = $(this).closest('tr').attr('expr')
                self.delTopic(expr);
            });
            $(".set-topic-count").blur(function(){
                let utils = TopicTable.Utils
                , $this = $(this)
                , expr = $this.closest('tr').attr('expr')
                , nowValue = $this.val()
                , maxTpoicCount = utils.getVal(self.inputData,expr)[1];
                self.updateInput(expr,nowValue,maxTpoicCount)
            });
            $(".set-topic-value").blur(function(){
                let $this = $(this)
                , expr = $this.closest('tr').attr('expr')
                , nowValue = $this.val();
                self.updateInput(expr,nowValue)
            })
        }
        //删除题目
        ,delTopic:function(expr){
            let utils = TopicTable.Utils
            , reg = /^(TOPIC_TYPE_CASE\.\d)/;
            //材料题,从新获取表达式
            reg.test(expr) && (expr = reg.exec(expr)[1]);
            let inputDataStruct = utils.getDataStruct(this.setting.inputData);
            //更新input数据源
            this.setting.inputData = utils.delData(this.setting.inputData,expr,inputDataStruct);
            //更新题目数据源
            this.setting.data = utils.delData(this.setting.data,expr,this.data);
            //重新初始化表格
            this.init();
        }
        //更新input数据
        ,updateInput:function(expr,nowValue,maxTpoicCount){
            let utils = TopicTable.Utils
            , inputDataStruct = utils.getDataStruct(this.setting.inputData)
            , value = utils.getVal(this.inputData,expr)
            , topics = utils.getVal(inputDataStruct,expr);
            //不是一个数
            !/^\d+(\.\d+)?$/.test(nowValue) && (nowValue = MINTOPICCOUNT)
            //maxTpoicCount存在，说明是：设置题目数量
            if(maxTpoicCount){
                nowValue > maxTpoicCount && (nowValue = maxTpoicCount)
                nowValue = parseInt(nowValue)
                value[0] = nowValue;
                topics.forEach(function(topic){
                    topic.randomCount = nowValue;
                })
            }else{//分数设置
                nowValue = Number( /^(\d+(\.\d+)?)?$/.exec(nowValue)[1] || MINTOPICCOUNT );
                //忽略小数点第一位后面的数
                value[2] = Number( nowValue.toString().match(/^\d+(?:\.\d{0,1})?/) );
                topics.forEach(function(topic){
                    topic.topicScore = nowValue;
                })
            }
            //重新初始化表格
            this.init();
        }
        ,setType(type){
            let utils = TopicTable.Utils
            , self = this
            , $setTopicCount = $(this.table).find('.set-topic-count');
            this.setting.type = type;
            if(type == 'random'){
                isInit = true;
                $setTopicCount.prop('disabled', false);
            }else{
                $setTopicCount.prop('disabled', true);
                if(isInit){
                    isInit = false
                    $setTopicCount.each(function(){
                        let expr = $(this).closest("tr").attr('expr');
                        let inputDataStruct = utils.getDataStruct(self.setting.inputData)
                        , topics = utils.getVal(inputDataStruct,expr)
                        topics.forEach(function(topic){
                            topic.randomCount = topics.length;
                        })
                        //更新input数据源
                        //self.setting.inputData = utils.delData(self.setting.inputData,expr,inputDataStruct);
                    });
                    self.init();
                }
            }
        }
    }
    
    let topicTableIns
    
    , topicTable = {
        render:function(options){
            isInit = true;
            options = $.extend(true,{},dftOpt,options);
            options = topicTable.dataCorrect(options,topicTableIns);
            topicTableIns = new TopicTable(options);
            return topicTableIns;
        }
        //数据修正
        ,dataCorrect:function(options,topicTableIns){
            let utils = TopicTable.Utils;
            options = topicTable.dataStruct(options);
            !options.isDepOldIns && (topicTableIns = null)
            if(utils.exist(options.data)){
                //data始终是最新传入的data
                if(topicTableIns){
                    topicTableIns.setting.data = options.data;
                    topicTableIns.setting.type = options.type;
                    options = $.extend(options,topicTableIns.setting);
                }
                //input:不存在的情况是topicTableIns或者input本身 不存在
                if(utils.notExist(options.inputData)){
                    let inputData = $.extend(true,{},{inputData:options.data}).inputData;
                    options.inputData = inputData;
                }else{
                    topicTable.handleInputData(options.data,options.inputData,'delInput');
                    topicTable.handleInputData(options.data,options.inputData,'addToInput');
                    options = topicTable.sortPos(options);
                }
                if(utils.notExist(options.inputData)){
                    let inputData = $.extend(true,{},{inputData:options.data}).inputData;
                    options.inputData = inputData;
                }
            }
            return options;
        }
        //处理data与inputData数据
        ,dataStruct:function(options){
            let utils = TopicTable.Utils;
            utils.exist(options.data) && (options.data = utils.parSubTree(options.data));
            options.inputData = utils.exist(options.inputData) && topicTable.getInputData(options.inputData,options.data) || null;
            return options;
        }
        ,getInputData:function(settings,data){
            let inputData = [],parentIds = [];
            for(let i = 0; i < settings.length; i++){
                let setting = settings[i];
                if(setting.parentId && !(parentIds.indexOf(setting.parentId) > -1)){
                    parentIds.push(setting.parentId);
                    let topicCase = {topicId:setting.parentId,topicType:'TOPIC_TYPE_CASE',difficulty:'DIFFICULT_TYPE_DIFFICULT'};
                    inputData.push(topicCase);
                }
                for(let j = 0; j < setting.topicList.length; j++){
                    let topicId = setting.topicList[j]
                    , newSetting = $.extend({},setting);
                    newSetting.topicId = topicId;
                    delete newSetting.topicList;
                    inputData.push(newSetting);
                }
            }
            return topicTable.utils.parSubTree(inputData,'parentId','topicId'); 
        }
        ,handleInputData:function(sourceData,inputData,method){
            if(method == 'delInput'){
                let temp = sourceData;
                sourceData = inputData;
                inputData = temp;
            }
            for(let i = 0; i < sourceData.length; i++){
                let topic = sourceData[i];
                for(let j = 0; j < inputData.length; j++){
                    let input = inputData[j] ;
                    if(input.topicId != topic.topicId){
                        if(j == inputData.length-1){
                            if(method == 'delInput'){
                                sourceData.splice(i,1)
                                i--;
                            }else{
                                inputData.push(topic);
                            }
                        }
                    }else{
                        break;
                    }
                }
            }
        }
        ,sortPos:function(options){
            let newInputData = [];
            options.data.forEach(function(topic,j){
                options.inputData.forEach(function(input,i){
                    if(topic.topicId == input.topicId){
                        //newInputData.splice(j, 0, input);
                        newInputData.push(input);
                    }
                })
            });

            options.inputData = newInputData;
            return options;
        }
    };
    topicTable.utils = TopicTable.Utils;
    return topicTable;
}));
